/**
 * @author:cavion(曹仁道)
 * @email:caorendao187@163.com
 * 2016年9月10日 
 */
package org.rk.core.jdbc.dao.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.rk.core.common.util.RkObjectUtil;
import org.rk.core.common.util.RkStrUtil;
import org.springframework.util.CollectionUtils;

/**
 * @author:cavion
 * @描述：
 * 2016年9月10日 上午11:03:37
 */
public class Condition {
	public static final String limit_start_param_name="start";
	public static final String limit_num_param_name="num";
	
	public static final String condi_type_and = " AND ";
    public static final String condi_type_or = " OR ";
    public static final String condi_type_limit = " LIMIT ";
    public static final String condi_type_order = " ORDER ";
    public static final String condi_type_group = " GROUP ";
    
    public static final String condi_mode_like = "LIKE";
    public static final String condi_mode_eq = "=";
    public static final String condi_mode_lt = "<";
    public static final String condi_mode_gt = ">";
    public static final String condi_mode_eq_lt = "<=";
    public static final String condi_mode_eq_gt = ">=";
    public static final String condi_mode_eq_in = "in";
    public static final String condi_mode_null = "IS NULL";
    
    public static final String condi_mode_order_asc = "ASC";
    public static final String condi_mode_order_desc = "DESC";
    
    public static String conditionSql(String paramKey,Object paramValue){
    	if(RkObjectUtil.isEmpty(paramValue)||!RkStrUtil.hasText(String.valueOf(paramValue))){
			return "";
		}
		String condiMode=condi_mode_eq;
		if(String.valueOf(paramValue).startsWith("%")||String.valueOf(paramValue).endsWith("%")){//检测百分号
			condiMode=condi_mode_like;
		}
		List<String> paramKeyList = new ArrayList<String>();
		String conditionSql=conditionSql(paramKey, paramKeyList, condiMode);
		return conditionSql;
    }
    public static String conditionSql(String dbFieldName,List<String> paramKeyList,String condiMode){
    	if(!RkStrUtil.hasText(condiMode)){
    		condiMode = condi_mode_eq;
    	}
    	StringBuffer sb = new StringBuffer();
    	sb.append(" " + dbFieldName);
    	sb.append(" " + condiMode);
    	if(condi_mode_eq_in.equals(condiMode)) {
    		sb.append(" (");
    		int i = 0;
    		for (String paramKey : paramKeyList) {
				if(i==0) {
					sb.append(" :" + paramKey);
				}else {
					sb.append(" ,:" + paramKey);
				}
			}
    		sb.append(") ");
    	}else {
    		sb.append(" :" + paramKeyList.get(0));
    	}
		return sb.toString();
    }
    
    public static String buildWhereSql(Class<?> clazz,List<ParamMap> paramMapList){
    	List<FieldInfo> fieldList=SQLUtils.loadPojoSqlInfo(clazz);
    	StringBuffer sb=new StringBuffer();
    	int whereNum=0;
    	for(FieldInfo fieldInfo:fieldList){
    		List<String> paramKeyInList = new ArrayList<String>();
	    	for(ParamMap paramMap:paramMapList){
	    		if(RkStrUtil.isEmpty(paramMap.getParamName())||RkObjectUtil.isEmpty(paramMap.getParamValue())
	    				||"%".equals(paramMap.getParamValue())||"%%".equals(paramMap.getParamValue())
	    				||"%null%".equals(paramMap.getParamValue())||"null%".equals(paramMap.getParamValue())||"%null".equals(paramMap.getParamValue())){//条件或名称是空的,或值只有%%，都不称为一个条件
	    			continue;
	    		}
	    		if(!paramMap.getCondiType().equals(condi_type_limit)&&!paramMap.getCondiType().equals(condi_type_order)&&!paramMap.getCondiType().equals(condi_type_group)){
    			
    				if(fieldInfo.getPojoFieldName()==paramMap.getParamName()){
    					if(condi_mode_eq_in.equals(paramMap.getCondiMode())) {
    						paramKeyInList.add(paramMap.getParamName());
    					} else {
    						sb.append(getWhereOrAnd(whereNum));
    						List<String> paramKeyList = new ArrayList<String>();
    						paramKeyList.add(paramMap.getParamName());
    						sb.append(conditionSql(fieldInfo.getDbFieldName(), paramKeyList, paramMap.getCondiMode()));
    						whereNum++;
    					}
    				}
    			}
    		}
	    	if(!CollectionUtils.isEmpty(paramKeyInList)) {
	    		sb.append(getWhereOrAnd(whereNum));
	    		sb.append(conditionSql(fieldInfo.getDbFieldName(), paramKeyInList, condi_mode_eq_in));
	    	}
    	}
    	return sb.toString();
    }
    private static String getWhereOrAnd(int whereNum) {
    	if(whereNum==0){
			return " where ";
		}else{
			return " and ";
		}
    }
    public static String buildWhereSql(List<ParamMap> paramMapList){
    	StringBuffer sb=new StringBuffer();
    	int whereNum=0;
    	Map<String,List<String>> paramInMap = new HashMap<String,List<String>>();
    	for(ParamMap paramMap:paramMapList){
    		if(RkStrUtil.isEmpty(paramMap.getParamName())||RkObjectUtil.isEmpty(paramMap.getParamValue())
    				||"%".equals(paramMap.getParamValue())||"%%".equals(paramMap.getParamValue())
    				||"%null%".equals(paramMap.getParamValue())){//条件或名称是空的,或值只有%%，都不称为一个条件
    			continue;
    		}
    		if(!paramMap.getCondiType().equals(condi_type_limit)&&!paramMap.getCondiType().equals(condi_type_order)&&!paramMap.getCondiType().equals(condi_type_group)){
    			if(condi_mode_eq_in.equals(paramMap.getCondiMode())) {
    				String paramName = paramMap.getParamName();
    				List<String> paramKeyInList = paramInMap.get(paramName);
    				if(RkObjectUtil.isEmpty(paramKeyInList)) {
    					paramKeyInList = new ArrayList<String>();
    					paramKeyInList.add(paramName);
    					paramInMap.put(paramMap.getParamName(), paramKeyInList);
    				} else {
    					paramKeyInList.add(paramMap.getParamName());
    				}
    			} else {
    				sb.append(getWhereOrAnd(whereNum));
    				List<String> paramKeyList = new ArrayList<String>();
					paramKeyList.add(paramMap.getParamName());
        			sb.append(conditionSql(paramMap.getParamName(), paramKeyList, paramMap.getCondiMode()));
        			whereNum++;
    			}
    		}
    	}
    	for (Entry<String, List<String>> paramIn : paramInMap.entrySet()) {
    		sb.append(getWhereOrAnd(whereNum));
    		sb.append(conditionSql(paramIn.getKey(), paramIn.getValue(), condi_mode_eq_in));
			whereNum++;
		}
    	return sb.toString();
    }

    public static String buildOrderSql(Class<?> clazz,List<ParamMap> paramMapList){
    	List<FieldInfo> fieldList=SQLUtils.loadPojoSqlInfo(clazz);
    	StringBuffer sb=new StringBuffer();
    	int orderNum=0;
    	for(ParamMap paramMap:paramMapList){
    		if(paramMap.getCondiType().equals(condi_type_order)){
    			if(orderNum==0){
    				sb.append(" ORDER BY ");
    			}else{
    				sb.append(" , ");
    			}
    			for(FieldInfo fieldInfo:fieldList){
    				if(fieldInfo.getPojoFieldName()==paramMap.getParamName()){
    					sb.append(fieldInfo.getDbFieldName()+" "+paramMap.getCondiMode());
    					break;
    				}
    			}
    			orderNum++;
    		}
    	}
    	return sb.toString();
    }
    public static String buildOrderSql(List<ParamMap> paramMapList){
    	StringBuffer sb=new StringBuffer();
    	int orderNum=0;
    	for(ParamMap paramMap:paramMapList){
    		if(paramMap.getCondiType().equals(condi_type_order)){
    			if(orderNum==0){
    				sb.append(" ORDER BY ");
    			}else{
    				sb.append(" , ");
    			}
    			sb.append(paramMap.getParamName()+" "+paramMap.getCondiMode());
    			orderNum++;
    		}
    	}
    	return sb.toString();
    }
    
    public static String buildLimiSql(String  sql,List<ParamMap> paramMapList){
    	StringBuffer sb=new StringBuffer();
    	int start=0;//初始默认
    	int perNum=10;//初始默认
    	for(ParamMap paramMap:paramMapList){
    		if(paramMap.getCondiType().equals(condi_type_limit)){
    			if(limit_start_param_name==paramMap.getParamName()){
    				start=Integer.parseInt(String.valueOf(paramMap.getParamValue()));
    			}else if(limit_num_param_name==paramMap.getParamName()){
    				perNum=Integer.parseInt(String.valueOf(paramMap.getParamValue()));
    			}
    		}
    	}
    	sb.append("select * from ( "+sql+" ) rk_limit_query");
    	sb.append(" LIMIT "+start+","+perNum+" ");
    	return sb.toString();
    }
    /**
     * @方法描述：构建goup by 部分
     * @author Cavion(曹仁道)
     * @return
     * 2016年11月12日 下午5:46:24
     */
    public static String buildGroupSql(Class<?> clazz,List<ParamMap> paramMapList){
    	//group by 和order by共存时，group by在前
    	List<FieldInfo> fieldList=SQLUtils.loadPojoSqlInfo(clazz);
    	StringBuffer sb=new StringBuffer();
    	int groupNum=0;
    	for(ParamMap paramMap:paramMapList){
    		if(paramMap.getCondiType().equals(condi_type_group)){
    			if(groupNum==0){
    				sb.append(" GROUP BY ");
    			}else{
    				sb.append(" , ");
    			}
    			for(FieldInfo fieldInfo:fieldList){
    				if(fieldInfo.getPojoFieldName()==paramMap.getParamName()){
    					sb.append(fieldInfo.getDbFieldName());
    					break;
    				}
    			}
    			groupNum++;
    		}
    	}
    	return sb.toString();
    }
    public static String buildGroupSql(List<ParamMap> paramMapList){
    	//group by 和order by共存时，group by在前
    	StringBuffer sb=new StringBuffer();
    	int groupNum=0;
    	for(ParamMap paramMap:paramMapList){
    		if(paramMap.getCondiType().equals(condi_type_group)){
    			if(groupNum==0){
    				sb.append(" GROUP BY ");
    			}else{
    				sb.append(" , ");
    			}
    			sb.append(paramMap.getParamName());
    			groupNum++;
    		}
    	}
    	return sb.toString();
    }
    public static String buildConditionSql(Class<?> clazz,List<ParamMap> paramMapList,String selectSql){
    	return buildLimiSql(selectSql+buildWhereSql(clazz, paramMapList)+" "+buildGroupSql(clazz,paramMapList)+" "+buildOrderSql(clazz, paramMapList)+" ",paramMapList);
    }
    public static String buildConditionSqlNoLimit(Class<?> clazz,List<ParamMap> paramMapList,String selectSql){
    	return selectSql+buildWhereSql(clazz, paramMapList)+" "+buildGroupSql(clazz,paramMapList)+" "+buildOrderSql(clazz, paramMapList)+" ";
    }
    public static String buildConditionSql(List<ParamMap> paramMapList,String selectSql){
    	return buildLimiSql(selectSql+buildWhereSql(paramMapList)+" "+buildGroupSql(paramMapList)+" "+buildOrderSql(paramMapList)+" ",paramMapList);
    }
    public static String buildConditionSqlNoLimit(List<ParamMap> paramMapList,String selectSql){
    	return selectSql+buildWhereSql(paramMapList)+" "+buildGroupSql(paramMapList)+" "+buildOrderSql(paramMapList);
    }
}
